use std::{fmt::{Debug, Display}, path::PathBuf};

use serde::{de, ser, Deserialize, Serialize};

use wtask_base::{error::WError, export::OwnedReadHalf, tcp::stream_read_raw};

use futures_util::{FutureExt, Stream};

#[derive(Debug, Serialize, Deserialize)]
pub struct Empty;

impl From<()> for Empty {
    fn from(_value: ()) -> Self {
        Self
    }
}

impl Display for Empty {
    fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        Ok(())
    }
}


#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WStatus {
    status: bool,
    log: Vec<String>,
}

impl From<(bool, Vec<String>)> for WStatus {
    fn from(value: (bool, Vec<String>)) -> Self {
        Self { status: value.0, log: value.1 }
    }
}

impl Display for WStatus {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.log.join("\n"))
    }
}






pub struct WStreamReader {
    pub stream_read: OwnedReadHalf,
    pub key: String,
}



impl Debug for WStreamReader {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "binary data")
    }
}

impl Display for WStreamReader {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "binary data")
    }
}



impl Serialize for WStreamReader {
    fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer {
        Err(ser::Error::custom("binary data reader"))
    }
}

impl<'de> Deserialize<'de> for WStreamReader {
    fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
        where
            D: serde::Deserializer<'de> {
        Err(de::Error::custom("binary data reader"))
    }
}


impl Stream for WStreamReader {
    type Item = Vec<u8>;
    fn poll_next(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Option<Self::Item>> {
        Box::pin(stream_read_raw(self.stream_read.as_ref(), &self.key))
            .poll_unpin(cx)
            .map(| v | v.ok())
    }
}





#[derive(Debug, Deserialize, Serialize)]
pub enum WRaw {
    Path(String),
    Raw(String),
}


impl From<&PathBuf> for WRaw {
    fn from(value: &PathBuf) -> Self {
        Self::Path(value.to_string_lossy().to_string())
    }
}


impl Display for WRaw {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Path(v) => write!(f, "{}", v),
            Self::Raw(v) => write!(f, "Binary data: {}", v),
        }
    }
}








#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WPath(String);

impl From<&PathBuf> for WPath {
    fn from(value: &PathBuf) -> Self {
        Self(value.to_string_lossy().to_string())
    }
}

impl TryFrom<WRaw> for WPath {
    type Error = WError;
    fn try_from(value: WRaw) -> Result<Self, Self::Error> {
        if let WRaw::Path(v) = value {
            Ok(Self(v))
        } else {
            Err(WError::Path)
        }
    }
}

impl From<WPath> for String {
    fn from(value: WPath) -> Self {
        value.0
    }
}

impl From<WPath> for PathBuf {
    fn from(val: WPath) -> Self {
        PathBuf::from(val.0)
    }
}

impl Display for WPath {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}



